package ngat.oss;

import ngat.message.OSS.*;
import ngat.util.logging.*;
import ngat.phase2.*; 
import ngat.instrument.*;
import ngat.phase2.nonpersist.*;

import java.io.*;
import java.util.*;
import java.lang.reflect.*;

import jyd.dbms.*;
import jyd.storable.*;
import jyd.collection.*;

/**
 * Action: Sent by USR to replace a Proposal specification after editing 
 * @author S.N.Fraser
 * $Id: EXPORT_PROPOSALImpl.java,v 1.1 2006/11/27 08:45:00 snf Exp $
 */
public class EXPORT_PROPOSALImpl extends TransactionImpl implements Serializable {

    /** The path used to locate the Proposal in the OSS database. */
    protected Path proposalPath;

    /** The Exportment (updated) Proposal to Export the one at 'path'.*/
    protected Proposal replacementProposal;

    /** The key to unlock the Proposal record. */
    protected int key;
 
    /** Create an EXPORT_PROPOSALImpl from the supplied request.*/  
    public EXPORT_PROPOSALImpl(EXPORT_PROPOSAL request) throws InvocationTargetException {
	super(request);
	this.proposalPath        = request.getProposalPath();
	this.replacementProposal = request.getReplacementProposal();
	this.key                 = request.getKey();
    }
    
    /**
     * Replaces the Proposal specified
     * @return Boolean or an OSS_Error.
     */
    public TRANSACTION_DONE exec() { 
	
	Proposal proposal = null;
	
	User user = null;
	
	Transaction t = null;
	try {
	    t = Transaction.current();
	    
	    // Locate the Proposal's owner (PI) from its path expression.
	    user = OSS_Utilities.fetchUser(proposalPath);

	    // See if User exists.
	    if (user == null) {
		logger.log(1, CLASS, id, "exec", 
			   "Could not find owner for Proposal: "
			   +proposalPath.toString());
		return error(TRANSACTION.PATH_RESOLUTION_ERROR,
				     "Could not find owner for Proposal:            "
				     +proposalPath.toString());
	    }

	    // Locate the Proposal record from its path expression.
	    proposal = null;
	    
	    try {
		proposal = OSS_Utilities.fetchProposal(proposalPath);
	    } catch (IOException iox) {
		logger.log(1, CLASS, id, "exec",
			   "Proposal: "+proposalPath.toString()+
			   " Error fetching from Database: "+iox);
		return error(TRANSACTION.DATABASE_READ_ERROR,			   
				     "Proposal: "+proposalPath.toString()+
				     " Error reading from database: "+iox);
	    }		
	    
	    // Check Proposal exists.
	    if (proposal == null) {
		logger.log(1, CLASS, id, "exec", 
			   "Proposal: "+proposalPath.toString()+" Not in database.");

		return error(TRANSACTION.PATH_RESOLUTION_ERROR, 
				     "Could not find Proposal: "
				     +proposalPath.toString());
	    }
		
	   // Check the Proposal is locked.
	    if (!proposal.isLocked()) {
		return error(TRANSACTION.DATABASE_OBJECT_NOT_LOCKED,
				     "Attempt to update Proposal which has not been locked: "
				     +proposalPath.toString());
	    }

	    // Make sure the key will unlock the Proposal.
	    if (proposal.getLock() != key) {		     
		return error(TRANSACTION.ILLEGAL_DATABASE_ACCESS,
				     "You do not have a valid key for this Proposal: "
				     +proposalPath.toString());
	    }

	    // OK we have the key
	    
	    //#### Should test here to make sure the allocated time has
	    //#### not been fiddled with !!!
	    
	    //  if ( prop.getAllocTime() == replacementProp.getAllocTime())...
	    
	    // Now unhook any CoIs from the Proposal (####record them!!)
	    User   coi = null;
	    Vector coilist = new Vector();
	    Tag    tag = null;
	    Root   root = OSS_Utilities.fetchRoot(proposalPath);
	    logger.log(1, CLASS, id, "exec",
		       "Root is: "+root.getName());
	    
	    if (root != null) {
		Iterator it1 = root.listAllTags();
		while (it1.hasNext()) {
		    tag = (Tag)it1.next();
		    Iterator it2 = tag.listAllUsers();
		    while (it2.hasNext()) {		
			coi = (User)it2.next();
			if (coi.findCoIProposal(proposal.getName()) != null) {
			    coi.deleteCoIProposal(proposal.getName());
			    coilist.addElement(coi); 
			    logger.log(1, CLASS, id, "exec", 
				       replacementProposal.getName()+
				       " detaching CoI: "+coi.getFullPath());
			}
		    }
		}
	    }

	    // Now we check to see if there were any FixedGroups which have been deleted.
	    logBuffer.append("\nChecking for any old fixed groups to detach:");
	    Iterator ig = proposal.listAllGroups();
	    while (ig.hasNext()) {
		Group group = (Group)ig.next();
		if (group instanceof FixedGroup) {
		    FixedGroup fg = (FixedGroup)group;
		    Scheduling.removeFixedGroup(fg);
		    logger.log(1, CLASS, id, "exec",
			       "Removed fixed group: "+fg.getName()+
			       " at "+sdf.format(new Date(fg.getFixedTime())));
		} 
	    }		
	    
	    // Delete the Proposal from the PI's list.
	    user.deleteProposal(proposal.getName());
			
	    // Slot the modified Proposal in.
	    user.addProposal(replacementProposal.getName());
	   
	    // Dont unlock it! BUT  Do set the export flag.
	    replacementProposal.setExported(true);			
	    replacementProposal.lock(key);

	    // The path should NOT need updating here as it should have been set
	    // already. Alternative would be to use updateChildren() in the addXX().
			
	    // Now reattach the recorded CoIs to the new Proposal.	
	    if (coilist != null) {
		Iterator it = coilist.iterator();
		while (it.hasNext()) {
		    coi = (User)it.next();
		    coi.addCoIProposal(replacementProposal.getName());
		    logger.log(1, CLASS, id, "exec", 
			       replacementProposal.getName()+
			       " re-attaching CoI: "+coi.getFullPath());
		}
	    }

	    logBuffer.append("\nAttaching new  fixed groups:");
	    Iterator ign = replacementProposal.listAllGroups();
	    while (ign.hasNext()) {
		Group group = (Group)ign.next();
		if (group instanceof FixedGroup) {
		    FixedGroup fg = (FixedGroup)group;
		    Scheduling.modifyFixedGroup(fg);
		    logger.log(1, CLASS, id, "exec", 
			       "Adding fixed group: "+fg.getName()+
			       " at "+sdf.format(new Date(fg.getFixedTime())));
		}
	    }
	    
	    // Save the Proposal.
	    try {
		OSS_Utilities.storeProposal(replacementProposal);
	    } catch (IOException ix) {
		logger.log(1, CLASS, id, "exec",
			   "Proposal ["+replacementProposal.getFullPath()+
			   "] Unable to Store: "+ix);
		return error(TRANSACTION.GROUP_UPDATE_ERROR, 
				     "Proposal ["+replacementProposal.getFullPath()+
				     "] Unable to Store: "+ix);
	    }
	    
	    EXPORT_PROPOSAL_DONE done = new EXPORT_PROPOSAL_DONE(id); 
	    done.setSuccessful(true);
	    return done;
	    
	} finally {
	    t.commit();
	}
	
    }
    
}


/** $Log: EXPORT_PROPOSALImpl.java,v $
/** Revision 1.1  2006/11/27 08:45:00  snf
/** Initial revision
/**
/** Revision 1.2  2001/04/27 17:22:00  snf
/** Adda proposal.
/**
/** Revision 1.1  2001/02/23 18:51:14  snf
/** Initial revision
/** */
